/*
 * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.baomidou.mybatisplus.advance.injector.processor;

import com.baomidou.mybatisplus.advance.injector.ASTBuilder;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.List;

/**
 * 判断 @TableName 的genMapper 如果为true，则自动生成一个Mapper，省去开发者自己写Mapper
 *
 * @author wanglei
 * @since 2022-03-14
 */
public class GenMapperProcessor implements MybatisPlusAPTProcessor {

    @Override
    public void generate(ASTBuilder astBuilder) {
        //如果需要生成Mapper则自动生成Mapper
        if (astBuilder.hasAnnotation(TableName.class, "genMapper", true)) {
            //没有Mapper的情况下，自动生成Mapper
            Long hasMapper = astBuilder.getJcClassDecl().defs.stream()
                    //开始过滤: 只对变量进行处理
                    .filter(it -> it.getKind().equals(Tree.Kind.INTERFACE) && "Mapper".equals(((JCTree.JCClassDecl) it).name.toString())).count();
            // 开发者别自己定义了一个Mapper，程序不在自动生成
            if (hasMapper == 0L) {
                JCTree.JCExpression idTypeRef = astBuilder.getIdTypeRef();
                // 找得到id字段
                if (idTypeRef != null) {

                    //  以下适配Mybatis plus 3.5.x 如果要适配mybatis plus4.x 需要放开上面的注释 改用上面的代码
                    JCTree.JCTypeApply implInterface = astBuilder.getTreeMaker().TypeApply(astBuilder.typeRef("com.baomidou.mybatisplus.core.mapper.BaseMapper"),
                            List.of(astBuilder.typeRef(astBuilder.getJcClassDecl().sym.toString())));
                    //生成Mapper接口
                    JCTree.JCClassDecl mapperInterface = astBuilder.getTreeMaker().ClassDef(
                            astBuilder.getTreeMaker().Modifiers(Flags.PUBLIC + Flags.STATIC + Flags.INTERFACE, List.nil()),
                            astBuilder.getNames().fromString(astBuilder.getJcClassDecl().getSimpleName() + "Mapper"),
                            List.nil(),
                            null,
                            List.of(implInterface), List.nil());
                    //把mapper接口拼接到类中
                    astBuilder.getJcClassDecl().defs = astBuilder.getJcClassDecl().defs.prepend(mapperInterface);
                }
            }
        }
    }


}
